#include <types.h>
#include <conio.h>
#include <schedule.h>

#include <sys/systub.h>
#include <sys/task.h>
#include <sys/thread.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/unistd.h>

typedef int	(*sysfn_t)(int, int, int, int);

struct sys_entry {
    sysfn_t sys_call;
};

#define SYS_ENTRY(n, fn)	{(sysfn_t)(fn)}

static struct sys_entry sys_entry[] = {
    /* 0 */ SYS_ENTRY(0, task_create),
    /* 1 */ SYS_ENTRY(1, thread_create),
    /* 2 */ SYS_ENTRY(2, task_terminate),
    /* 3 */ SYS_ENTRY(3, task_setname),
    /* 4 */ SYS_ENTRY(4, task_suspend),
    /* 5 */ SYS_ENTRY(5, task_resume),
    /* 6 */ SYS_ENTRY(6, task_self),
    /* 7 */ SYS_ENTRY(7, thread_load),
    /* 8 */ SYS_ENTRY(8, thread_self),
    /* 9 */ SYS_ENTRY(9, thread_terminate),
    /* 10 */ SYS_ENTRY(10, thread_yield),
    /* 11 */ SYS_ENTRY(11, thread_suspend),
    /* 12 */ SYS_ENTRY(12, thread_resume),
    /* 13 */ SYS_ENTRY(13, vm_alloc),
    /* 14 */ SYS_ENTRY(14, vm_free),
    /* 15 */ SYS_ENTRY(15, vm_map),
    /* 16 */ SYS_ENTRY(16, vm_attribute),
    /* 17 */ SYS_ENTRY(17, msg_receive),
    /* 18 */ SYS_ENTRY(18, msg_reply),
    /* 19 */ SYS_ENTRY(19, msg_send),
    /* 20 */ SYS_ENTRY(20, ipc_create),
    /* 21 */ SYS_ENTRY(21, ipc_destroy),
    /* 22 */ SYS_ENTRY(22, ipc_lookup),
    /* 23 */ SYS_ENTRY(23, sem_init),
    /* 24 */ SYS_ENTRY(24, sem_destroy),
    /* 25 */ SYS_ENTRY(25, sem_post),
    /* 26 */ SYS_ENTRY(26, sem_trywait),
    /* 27 */ SYS_ENTRY(27, sem_getval),
    /* 28 */ SYS_ENTRY(28, sem_wait),
};

#define NSYSCALLS	(int)sizeof(sys_entry)/sizeof(sys_entry[0])

int syscall_dispatch(int r0, int r1, int r2, int r3,
	int sc_id)
{
    int retval = -1;
    const struct sys_entry *callfn;
    
    if (sc_id < NSYSCALLS) {
	callfn = &sys_entry[sc_id];
	retval = (*callfn->sys_call)(r0, r1, r2, r3);
    }
    
    return (retval);
}

